/**
 * A convenience class defined for add, subtracting, and scaling vectors.
 */
function Vector2d(X,Y) {
	this.x = X;
	this.y = Y;
}

Vector2d.prototype.add = function (vec) {
	return new Vector2d(this.x + vec.x, this.y + vec.y);
};

Vector2d.prototype.sub = function(vec) {
	return new Vector2d(this.x - vec.x, this.y - vec.y);
};

Vector2d.prototype.scale = function(constant) {
	return new Vector2d(constant * this.x, constant * this.y);
};

/**
 * Fake bezier--We actually use the control points as points also.
 * Even though the control points don't really lie on the bezier curve
 * as the subdivisions increase, the control points get closer and closer
 * to the actual bezier curve.
 *
 * @param 	p0 	Bezier curve ending endpoint
 * @param 	c1 	Control point 1
 * @param 	c2	Control point 2
 * @param 	p3	Bezier curve starting endpoint
 * @param	div	Number of divisions to divide curve
 * @return	Vector2d Array containing points on curve
 *
 * TODO Use adaptive tesslation?
 */
function getBezier(p0, c1, c2, p3, div, segment){
	if(div > 0){
		// Lots of linear interpolations
		var c1_0 = p0.add(c1).scale(0.5);
		var n0 = c1.add(c2).scale(0.5);
		var c2_1 =  c2.add(p3).scale(0.5);

		var c1_1 = c1_0.add(n0).scale(0.5);
		var c2_0 = n0.add(c2_1).scale(0.5);

		var p03 = c1_1.add(c2_0).scale(0.5);

		// Continue to subdivide
		var curve1;
		var curve2;
		var curveSegment;

		if(segment == "first-half" || segment == "whole"){
			curve1 = getBezier(p0, c1_0, c1_1, p03, div-1, "whole");
			curveSegment = curve1;
		}
		if(segment == "second-half" || segment == "whole"){
			curve2 = getBezier(p03, c2_0, c2_1, p3, div-1, "whole");
			curveSegment = curve2;
		}
		if(segment == "whole"){
			// Get rid of duplicate point in middle and combine the 2 havles
			curve1.pop();
	        curveSegment = curve1.concat(curve2);
		}

		return curveSegment;
	} else {
		// Base case (no more divisions)
		return new Array(p0,c1,c2,p3);
	}
}

/**
 * Returns control points based on 2 endpoints and the amount parameter
 *
 * @param 	to 		Bezier curve ending endpoint
 * @param 	from 	Bezier curve starting endpoint
 * @param 	amount	Value between 0 and 1 determining the rotation of the
 * 					 control points between 0 and 90 degrees
 * @return			Vector2d Array containing the 2 control points
 */
function getControlPoints(to, from, magScale, rotation){
	var dirX = to.x - from.x;
	var dirY = to.y - from.y;

	var mag = Math.sqrt(dirX*dirX + dirY*dirY);
	if (mag === 0) {
		// Line has no length
		return new Array(to, from);
	}
	// Determine how far away the control points should be from end points.
	var length = mag * magScale;

	// Normalize vector
	dirX /= mag;
	dirY /= mag;

	// 2d rotation by 30 degrees
	var angle = rotation;
	var sin =  Math.sin(angle);
	var cos = Math.cos(angle);

	var rotX = cos * dirX - sin * dirY; //x' = cos(t)*x - sin(t)*y
	var rotY = sin * dirX + cos * dirY; //y' = sin(t)*x + cos(t)*y
	// sin(-t) = -sin(t) and cos(-t) = cos(t)
	var rotNegX = cos * -dirX - sin * dirY; //x' = cos(-t)*-x - sin(-t)*-y
	var rotNegY = sin * dirX - cos * dirY; //y' = sin(-t)*-x + cos(-t)*-y

	// Get one leg of the arrow
	var x1 = rotX*length + from.x;
	var y1 = rotY*length + from.y;

	// Get parallel leg of arrow
	var x2 = rotNegX*length + to.x;
	var y2 = rotNegY*length + to.y;

	/* Weird code: this is used for flipping the bezier curve making the order
	 * of to and from irrelevant.*/
	if (dirX < 0 || (dirX === 0 && dirY < 0)) {
		x2 = -rotX*length+ to.x;
		y2 = -rotY*length + to.y;

		// Get parallel leg of arrow
		x1 = -rotNegX*length + from.x;
		y1 = -rotNegY*length + from.y;
	}
	return new Array(new Vector2d(x2,y2), new Vector2d(x1,y1));
}
